﻿<!DOCTYPE html>
<html class="theme theme-white">
<head>
<meta charset="utf-8">
<title>redis学习---redis主从复制机制</title>
<link href="https://www.zybuluo.com/static/assets/template-theme-white.css" rel="stylesheet" media="screen">
<style type="text/css">

#wmd-preview h1  {
    color: #0077bb; /* 将标题改为蓝色 */
}</style>
</head>
<body class="theme theme-white">
<div id="wmd-preview" class="wmd-preview wmd-preview-full-reader"><div class="md-section-divider"></div><div class="md-section-divider"></div><h1 data-anchor-id="7sby" id="redis学习-redis主从复制机制">redis学习---redis主从复制机制</h1><div class="md-section-divider"></div><h2 data-anchor-id="p5kj" id="目录">目录</h2><ul data-anchor-id="bs3v">
<li>简介</li>
<li>架构图</li>
<li>主从复制实践</li>
<li>主从复制原理</li>
<li>总结</li>
<li>相关配置说明</li>
</ul><div class="md-section-divider"></div><h2 data-anchor-id="hmxk" id="1-简介">1. 简介：</h2><p data-anchor-id="jrmk">就是我们常见的master/slave模式，把redis的数据库复制多个副本部署在不同的服务器上，如果其中一台服务器出现故障，也能快速迁移到其他服务器上提供服务</p><div class="md-section-divider"></div><h2 data-anchor-id="1fxw" id="2-架构图">2. 架构图</h2><p data-anchor-id="jxpy"><img src="http://www.chengqj.com/static/images/redis/redis%E4%B8%BB%E4%BB%8E%E6%9E%B6%E6%9E%84%E5%9B%BE.png" alt="redis主从复制架构图"></p><div class="md-section-divider"></div><h2 data-anchor-id="763j" id="3-主从复制实践">3. 主从复制实践</h2><div class="md-section-divider"></div><h3 data-anchor-id="opk2" id="31-从服务配置redisconf">3.1 从服务配置redis.conf</h3><div class="md-section-divider"></div><pre class="prettyprint linenums prettyprinted" data-anchor-id="q8nm"><ol class="linenums"><li class="L0"><code class="language-properties"><span class="com"># bind 127.0.0.1 //主从都注释掉，可以让别的主机访问</span></code></li><li class="L1"><code class="language-properties"><span class="pln">slaveof </span><span class="lit">192.168</span><span class="pun">.</span><span class="lit">127.131</span><span class="pln"> </span><span class="lit">6379</span><span class="pln"> </span><span class="com">//设置主服务的IP+端口</span></code></li></ol></pre><div class="md-section-divider"></div><h3 data-anchor-id="evzt" id="32-用info-replication命令查看结果">3.2 用info replication命令查看结果</h3><p data-anchor-id="z6ks"><img src="http://www.chengqj.com/static/images/redis/info%20replication.png" alt="info replication结果">)</p><div class="md-section-divider"></div><h2 data-anchor-id="d26c" id="4-主从复制原理">4. 主从复制原理</h2><div class="md-section-divider"></div><h3 data-anchor-id="za4q" id="41-三种复制方式">4.1 三种复制方式：</h3><ol data-anchor-id="4atp">
<li>全量备份</li>
<li>增量备份</li>
<li>无磁盘备份</li>
</ol><div class="md-section-divider"></div><h3 data-anchor-id="ctyg" id="42-全量备份">4.2 全量备份</h3><p data-anchor-id="u7mp"><strong>流程：</strong></p><ol data-anchor-id="21la">
<li>从服务器向主服务发送SYNC命令</li>
<li>主服务器收到SYNC命令后执行bgsave命令，在后台生成RDB文件，并用一个缓存区记录从现在开始执行的写命令</li>
<li>将RDB生成的快照文件发送给从服务器</li>
<li>从服务器收到快照后载入该文件，将自己服务器数据更新到和主服务器执行bgsave时同样的数据</li>
<li>主服务器将记录在缓冲区记录的数据发送给从服务器，从服务器执行这些命令，将自己数据和主服务器数据同步</li>
</ol><p data-anchor-id="n10i"><strong>时序图：</strong> <br>
<img src="http://www.chengqj.com/static/images/redis/%E5%85%A8%E9%87%8F%E6%9B%B4%E6%96%B0.png" alt="全量备份" title=""> <br>
<strong>说明：</strong> 主从策略是容忍一定时间内主从不一致，是最终的一致性。</p><p data-anchor-id="e0p2"><strong>配置参数说明：</strong></p><div class="md-section-divider"></div><pre class="prettyprint linenums prettyprinted" data-anchor-id="ubfi"><ol class="linenums"><li class="L0"><code class="language-properties"><span class="com">#表示只有当3个或以上的slave连接到master，master才是可写的</span></code></li><li class="L1"><code class="language-properties"><span class="pln">min</span><span class="pun">-</span><span class="pln">slaves</span><span class="pun">-</span><span class="pln">to</span><span class="pun">-</span><span class="pln">write </span><span class="lit">3</span><span class="pln"> </span></code></li><li class="L2"><code class="language-properties"><span class="com">#表示允许slave最长失去连接的时间，如果10秒还没收到slave的响应，则master认为该slave已断开</span></code></li><li class="L3"><code class="language-properties"><span class="pln">min</span><span class="pun">-</span><span class="pln">slaves</span><span class="pun">-</span><span class="pln">max</span><span class="pun">-</span><span class="pln">lag </span><span class="lit">10</span><span class="pln"> </span></code></li></ol></pre><div class="md-section-divider"></div><h3 data-anchor-id="o5fy" id="43-增量备份-从28版本之后开始支持">4.3 增量备份 从2.8版本之后开始支持</h3><p data-anchor-id="ieph"><strong>流程：</strong> <br>
 1. 短线重连后，从服务器向主服务器发送PSYNC命令 <br>
 2. 主服务器向从服务器返回CONTINUE回复，准备开始增量备份 <br>
 3. 从服务接收到CONTINUE回复后准备开始复制 <br>
 4. 主从同步上次的offset数据 <br>
 5. 主服务器发送断连后的数据给从服务器 <br>
 6. 从服务器执行接收到的命令</p><p data-anchor-id="tg8q"><strong>时序图：</strong> <br>
<img src="http://www.chengqj.com/static/images/redis/%E5%A2%9E%E9%87%8F%E6%9B%B4%E6%96%B0.png" alt="增量备份" title=""></p><p data-anchor-id="7xur">offset数据可以通过info replication查看</p><p data-anchor-id="tjre"><img src="http://www.chengqj.com/static/images/redis/%E5%A2%9E%E9%87%8F%E5%A4%87%E4%BB%BD%E7%9A%84offset.png" alt="增量备份的offset.png" title=""></p><div class="md-section-divider"></div><h3 data-anchor-id="5xd8" id="44-无磁盘复制">4.4 无磁盘复制</h3><p data-anchor-id="1rc6">master**在内存中直接创建rdb，然后发送给slave，不会在自己本地落地磁盘了,整体流程和RDB的方式差不多，只是少了写入RDB文件的过程</p><div class="md-section-divider"></div><pre class="prettyprint linenums prettyprinted" data-anchor-id="1mue"><ol class="linenums"><li class="L0"><code class="language-properties"><span class="pln">repl</span><span class="pun">-</span><span class="pln">diskless</span><span class="pun">-</span><span class="pln">sync yes</span></code></li></ol></pre><div class="md-section-divider"></div><h2 data-anchor-id="e22q" id="5-总结">5. 总结：</h2><p data-anchor-id="nhca">Redis目前的复制是异步的，只保证最终一致性，而不是强一致性（主从数据库的更新还是分先后，先主后从）。要是一致性要求高的应用，目前还是读写都在主库上去</p><div class="md-section-divider"></div><h2 data-anchor-id="x10o" id="6-相关配置说明">6. 相关配置说明</h2><p data-anchor-id="r1fv">来源：<a href="https://www.cnblogs.com/zhoujinyi/p/5570024.html" target="_blank">https://www.cnblogs.com/zhoujinyi/p/5570024.html</a></p><div class="md-section-divider"></div><pre class="prettyprint linenums prettyprinted" data-anchor-id="j6y6"><ol class="linenums"><li class="L0"><code class="language-properties"><span class="com"># 主从配置选项 slaveof复制对应的master</span></code></li><li class="L1"><code class="language-properties"><span class="com"># slaveof &lt;masterip&gt; &lt;masterport&gt;</span></code></li><li class="L2"><code class="language-properties"></code></li><li class="L3"><code class="language-properties"><span class="com"># 如果服务端配置了密码，从库连接需要设置密码</span></code></li><li class="L4"><code class="language-properties"><span class="com"># masterauth &lt;master-password&gt;</span></code></li><li class="L5"><code class="language-properties"></code></li><li class="L6"><code class="language-properties"><span class="com"># 作为从服务器，默认情况下是只读的（yes）</span></code></li><li class="L7"><code class="language-properties"><span class="pln">slave</span><span class="pun">-</span><span class="pln">read</span><span class="pun">-</span><span class="pln">only yes</span></code></li><li class="L8"><code class="language-properties"></code></li><li class="L9"><code class="language-properties"><span class="com"># 是否使用socket方式复制数据。目前redis复制提供两种方式，disk和socket。如果新的slave连上来或者重连的slave无法部分同步，就会执行全量同步，master会生成rdb文件。有2种方式：disk方式是master创建一个新的进程把rdb文件保存到磁盘，再把磁盘上的rdb文件传递给slave。socket是master创建一个新的进程，直接把rdb文件以socket的方式发给slave。disk方式的时候，当一个rdb保存的过程中，多个slave都能共享这个rdb文件。socket的方式就的一个个slave顺序复制。在磁盘速度缓慢，网速快的情况下推荐用socket方式</span></code></li><li class="L0"><code class="language-properties"><span class="pln">repl</span><span class="pun">-</span><span class="pln">diskless</span><span class="pun">-</span><span class="pln">sync </span><span class="kwd">no</span></code></li><li class="L1"><code class="language-properties"></code></li><li class="L2"><code class="language-properties"><span class="com">#diskless复制的延迟时间，防止设置为0。一旦复制开始，节点不会再接收新slave的复制请求直到下一个rdb传输。所以最好等待一段时间，等更多的slave连上来。</span></code></li><li class="L3"><code class="language-properties"><span class="pln">repl</span><span class="pun">-</span><span class="pln">diskless</span><span class="pun">-</span><span class="pln">sync</span><span class="pun">-</span><span class="pln">delay </span><span class="lit">5</span></code></li><li class="L4"><code class="language-properties"></code></li><li class="L5"><code class="language-properties"><span class="com">#slave根据指定的时间间隔向服务器发送ping请求。时间间隔可以通过 repl_ping_slave_period 来设置，默认10秒。</span></code></li><li class="L6"><code class="language-properties"><span class="com"># repl-ping-slave-period 10</span></code></li><li class="L7"><code class="language-properties"></code></li><li class="L8"><code class="language-properties"></code></li><li class="L9"><code class="language-properties"><span class="com">#复制连接超时时间。master和slave都有超时时间的设置。master检测到slave上次发送的时间超过repl-timeout，即认为slave离线，清除该slave信息。slave检测到上次和master交互的时间超过repl-timeout，则认为master离线。需要注意的是repl-timeout需要设置一个比repl-ping-slave-period更大的值，不然会经常检测到超时。</span></code></li><li class="L0"><code class="language-properties"><span class="com"># repl-timeout 60</span></code></li><li class="L1"><code class="language-properties"></code></li><li class="L2"><code class="language-properties"><span class="com">#复制缓冲区大小，这是一个环形复制缓冲区，用来保存最新复制的命令。这样在slave离线的时候，不需要完全复制master的数据，如果可以执行部分同步，只需要把缓冲区的部分数据复制给slave，就能恢复正常复制状态。缓冲区的大小越大，slave离线的时间可以更长，复制缓冲区只有在有slave连接的时候才分配内存。没有slave的一段时间，内存会被释放出来，默认1m。</span></code></li><li class="L3"><code class="language-properties"><span class="com"># repl-backlog-size 5mb</span></code></li><li class="L4"><code class="language-properties"></code></li><li class="L5"><code class="language-properties"><span class="com">#master没有slave一段时间会释放复制缓冲区的内存，repl-backlog-ttl用来设置该时间长度。单位为秒。</span></code></li><li class="L6"><code class="language-properties"><span class="com"># repl-backlog-ttl 3600</span></code></li><li class="L7"><code class="language-properties"></code></li><li class="L8"><code class="language-properties"><span class="com">#当master不可用，Sentinel会根据slave的优先级选举一个master。最低的优先级的slave，当选master。而配置成0，永远不会被选举。</span></code></li><li class="L9"><code class="language-properties"><span class="pln">slave</span><span class="pun">-</span><span class="pln">priority </span><span class="lit">100</span></code></li><li class="L0"><code class="language-properties"></code></li><li class="L1"><code class="language-properties"><span class="com">#redis提供了可以让master停止写入的方式，如果配置了min-slaves-to-write，健康的slave的个数小于N，mater就禁止写入。master最少得有多少个健康的slave存活才能执行写命令。这个配置虽然不能保证N个slave都一定能接收到master的写操作，但是能避免没有足够健康的slave的时候，master不能写入来避免数据丢失。设置为0是关闭该功能。</span></code></li><li class="L2"><code class="language-properties"><span class="com"># min-slaves-to-write 3</span></code></li><li class="L3"><code class="language-properties"></code></li><li class="L4"><code class="language-properties"><span class="com">#延迟小于min-slaves-max-lag秒的slave才认为是健康的slave。</span></code></li><li class="L5"><code class="language-properties"><span class="com"># min-slaves-max-lag 10</span></code></li></ol></pre><hr></div>
</body>
</html>